﻿/****************************************************************************
Copyright (c) 2014-2015 凌惊雪 微信:Lingjingxue 邮箱:lingjingxue@sina.com QQ:271487457

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UtilLib
{
    /// <summary>
    /// 公共函数类  随机
    /// </summary>
    public static partial class Util
    {
        /// <summary>
        /// 随机种子
        /// </summary>
        public static Random Random = new Random(Environment.TickCount);
        /// <summary>
        /// 
        /// </summary>
        public static void RandomReset()
        {
            Random = new Random(Environment.TickCount);
        }
        /// <summary>
        /// 随机一个Int
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        public static int Rand(int max)
        {
            return Random.Next(max);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static int Rand(int min, int max)
        {
            return Random.Next(min, max);
        }
        /// <summary>
        /// 随机一个BOOL
        /// </summary>
        /// <returns></returns>
        public static bool RandBool()
        {
            return Random.NextDouble() < 0.5;
        }
        /// <summary>
        /// 随机一个BOOL 和v比较
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        public static bool RandBool(float v)
        {
            return Random.NextDouble() < v;
        }
        /// <summary>
        /// 随机long
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static long Rand(long min, long max)
        {
            long result;
            long rmax = max, rmin = min;
            if (min > max)
            {
                rmax = min;
                rmin = max;
            }
            double Key = Random.NextDouble();
            result = rmin + (long)((rmax - rmin) * Key);
            return result;
        }
        /// <summary>
        /// 随机long
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        public static long Rand(long max)
        {
            return Rand(0, max);
        }
        /// <summary>
        /// 随机一个 0-range 的值 判断是否小于 lessthen
        /// </summary>
        /// <param name="range"></param>
        /// <param name="lessthen"></param>
        /// <returns></returns>
        public static bool RandLessThen(int range, int lessthen)
        {
            var rd = Random.Next(range);
            return (rd < lessthen);
        }
        /// <summary>
        /// 随机枚举
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T RandEnum<T>()
            where T : Enum
        {
            Type type = typeof(T);
            if (type.IsEnum == false) throw new InvalidOperationException();

            var array = Enum.GetValues(type);
            var index = Random.Next(array.GetLowerBound(0), array.GetUpperBound(0) + 1);
            return (T)array.GetValue(index);
        }

        /// <summary>
        /// 生成指定范围内的不重复随机数
        /// </summary>
        /// <param name="count">随机数个数</param>
        /// <param name="minNum">随机数下限（随机数可以取该下界值）</param>
        /// <param name="maxNum">随机数上限（随机数不能取该上界值）</param>
        /// <returns></returns>
        public static int[] RandomMultiple(int count, int minNum, int maxNum)
        {
            int[] result = new int[count];
#if true
            //方法2：利用Hashtable。
            if (maxNum >= minNum)
            {
                Hashtable hashtable = new Hashtable();
                for (int i = 0; hashtable.Count < count; i++)
                {
                    int nValue = Random.Next(minNum, maxNum);
                    if (!hashtable.ContainsValue(nValue))
                    {
                        result[hashtable.Count] = nValue;
                        hashtable.Add(nValue, nValue);
                    }
                }
            }
#else
            //方法1：思想是用一个数组来保存索引号，先随机生成一个数组位置，然后把随机抽取到的位置的索引号取出来，并把最后一个索引号复制到当前的数组位置，然后使随机数的上限减一，具体如：先把这100个数放在一个数组内，每次随机取一个位置（第一次是1-100，第二次是1-99，...），将该位置的数用最后的数代替。
            int j;
            for (j = 0; j < count; j++)
            {
                int i = Rd.Next(minNum, maxNum);
                int num = 0;
                for (int k = 0; k < j; k++)
                {
                    if (result[k] == i)
                    {
                        num = num + 1;
                    }
                }
                if (num == 0)
                {
                    result[j] = i;
                }
                else
                {
                    j = j - 1;
                }
            }
#endif
            return result;
        }


        #region 生成随机字符串
        private static char[] 随机字符大小写数字 = {
            '0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
        };
        private static char[] 随机字符小写数字 = {
            '0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
        };
        private static char[] 随机字符小写 = {
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
        };
        private static char[] 随机字符数字 = {
            '0','1','2','3','4','5','6','7','8','9'
        };
        /// <summary>
        /// 随机字符大小写数字
        /// </summary>
        /// <param name="ruler">0=随机字符大小写数字 1=随机字符小写数字</param>
        /// <param name="count">生成数量</param>
        /// <param name="length">字符串长度</param>
        /// <param name="randseed">固定随机种子 0=随机</param>
        /// <returns></returns>
        public static List<string> RandomString(int ruler, int count, int length, int randseed = 0)
        {
            var result = new List<string>();
            var rand = Util.Random;
            if (randseed != 0)
            {
                rand = new Random(randseed);
            }
            var 随机字符 = 随机字符大小写数字;
            if (ruler == 1)
            {
                随机字符 = 随机字符小写数字;
            }
            for (int i = 0; i < count; i++)
            {
                StringBuilder sb = new StringBuilder();
                var len = 随机字符.Length;
                for (int j = 0; j < length; j++)
                {
                    sb.Append(随机字符[rand.Next(len)]);
                }
                result.Add(sb.ToString());
            }
            return result;
        }
        #endregion

    }
}